# -*-* encoding:UTF-8 -*-
# author            : mengy
# date              : 2019/5/24
# python-version    : Python 3.7.0
# description       : MongoDB 操作

from pymongo import *


class MongoDbClient:

    def __init__(self, host='localhost', port=27017, db_name='crawl', collection='sina_userinfo'):
        self.__database = MongoClient(host, port).get_database(db_name)
        self.__collection = self.__database.get_collection(collection)

    def get_collections(self):
        """
        查询所有的集合（不包括系统集合）\n
        :return:
        """
        return self.__database.list_collection_names(include_system_collections=False)

    def insert_one(self, map, **kwargs):
        """
        插入一条记录\n
        :param map:
        :param kwargs:
        :return:
        """
        self.__collection.insert_one(map, **kwargs)

    def insert_many(self, *args):
        """
        批量插入记录\n
        :param args:
        :return:
        """
        self.__collection.insert_many(*args)

    def find_one(self, *args, **kwargs):
        """
        查询一条匹配的记录\n
        :param args:
        :param kwargs:
        :return:
        """
        return self.__collection.find_one(*args, **kwargs)

    def pop(self, *args, **kwargs):
        """
        查询一条匹配的记录，并从mongodb删除\n
        :param args:
        :param kwargs:
        :return:
        """
        return self.__collection.find_one_and_delete(*args, kwargs)

    def find(self, *args, **kwargs):
        """
        查找一条或多条记录\n
        $lt（小于）， $gt（大于）， $lte（小于等于）， $gte（大于等于）， $ne（不等于）\n
        :param args:
        :param kwargs:
        :return:
        """
        return self.__collection.find(*args, **kwargs)

    def count(self, filter, **kwargs):
        """
        统计符合条件的记录条数\n
        :param filter:
        :param kwargs:
        :return:
        """
        return self.__collection.count_documents(filter, **kwargs)

    def delete_one(self, filter):
        """
        删除匹配的一条记录\n
        :param filter:
        :return:
        """
        self.__collection.delete_one(filter)

    def delete_many(self, filter):
        """
        批量删除匹配的记录\n
        :param filter:
        :return:
        """
        self.__collection.delete_many(filter)

    def save(self, destination):
        """
        如果目标对象（destination）id，存在，则修改，如果不存在，则创建\n
        注：与 update 的区别在于，save 修改是整个对象修改，也就意味着修改时需要构造完整的对象（包括不需要修改的值），而 update 只修改指定的部分\n
        :param destination: 目标对象\n
        :return:
        """
        self.__collection.save(destination)

    def update(self, origin, destination):
        """
        该方法已过期，不推荐使用，替代方法请使用 replace_one()
        :param origin:
        :param destination:
        :return:
        """
        self.__collection.update(origin, destination)

    def replace_one(self, origin, destination):
        """
        替换一条记录\n
        :param origin:
        :param destination:
        :return:
        """
        self.__collection.replace_one(origin, destination)

    def update_one(self, filter, destination, upsert):
        """
        修改一条记录\n
        :param filter:
        :param destination:
        :param upsert: 更新或插入，默认为 False
        :return:
        """
        self.__collection.update_one(filter, destination, upsert)

    def update_many(self, filter, destination):
        """
        批量修改匹配的记录\n
        :param filter:
        :param destination:
        :return:
        """
        self.__collection.update_many(filter, destination)

    # def aggregate(self):
    #     return self.__collection.aggregate()

    def aggregate(self, pipeline, **kwargs):
        """
        聚合查询\n
        :param pipeline:
        :param kwargs:
        :return:
        """
        return self.__collection.aggregate(pipeline, **kwargs)


if __name__ == '__main__':
    db = MongoDbClient()
    # map = [{'nick_name': '孟非', 'webo_num': '127', 'follow_num': '32', 'fans_num': '33595308', 'gender': '男',
    #         'district': '江苏', 'birthday': '1971-10-12', 'brief_intro': '', 'identify': '主持人',
    #         'internet': 'http://weibo.com/jsbcmf', 'mobile': 'https://weibo.cn/jsbcmf'},
    #        {'nick_name': '孟非1', 'webo_num': 127, 'follow_num': '32', 'fans_num': '33595308', 'gender': '男',
    #         'district': '江苏', 'birthday': '1971-10-12', 'brief_intro': '', 'identify': '主持人',
    #         'internet': 'http://weibo.com/jsbcmf', 'mobile': 'https://weibo.cn/jsbcmf'}]
    # db.insert_many(map)

    # [print(item) for item in db.find({'nick_name': '孟非1'}).sort('webo_num', ASCENDING)]

    # print(db.pop({'nick_name': '孟非', 'gender': '男'}))

    # print(db.count({'gender': '男'}))
    # print(db.find_one({"webo_num": {"$lt": 1000}}))

    # print(db.get_collections())

    # [print(item) for item in db.find({'nick_name': '孟非'}).sort('webo_num', ASCENDING)]
    # origin = db.find_one({'nick_name': '孟非'})
    # destination = origin.copy()
    # destination.update({'nick_name': '孟非2'})
    # destination2 = {'nick_name': '孟非5', 'webo_num': 127, 'follow_num': '32', 'fans_num': '33595308', 'gender': '男',
    #                 'district': '江苏', 'birthday': '1971-10-12', 'brief_intro': '', 'identify': '主持人',
    #                 'internet': 'http://weibo.com/jsbcmf', 'mobile': 'https://weibo.cn/jsbcmf'}
    # db.replace_one(origin, destination2)
    # db.update_many({'nick_name': '孟非1'}, {"$set": {"webo_num": 123698}})
    # [print(item) for item in db.find({'nick_name': '孟非5'}).sort('webo_num', ASCENDING)]

    # db.delete_many({'nick_name': '孟非1'})

    # db.delete_many({})

    # 聚合查询
    match = {
        'district': {
            '$nin': ['null', '']
        }
    }

    groupby = 'province'


    def extract(district: str) -> str:
        return district.split(' ')[0]


    group = {
        '_id': "$%s" % (extract(groupby) if groupby else None),
        'count': {'$sum': 1}

    }

    res = db.aggregate([
        {'$match': match},
        {'$group': group},
    ])
    result = [(re.get('_id'), re.get('count')) for re in res]
    print(result)

    # for item in db.find({}):
    #     # print(item)
    #     item.update({'province': str(item.get('district')).split(' ')[0] if item.get('district') else ''})
    #     # print(item)
    #     db.save(item)
